package com.card.hwatt.assembler;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;

import com.card.hwatt.dto.Card;
import com.card.hwatt.dto.CardRecord;
import com.card.hwatt.dto.Employee;
import com.card.hwatt.dto.NightCheck;
import com.card.hwatt.dto.Schedule;

/**
 * 员工刷脸记录统计
 * 
 * @author Administrator
 * 
 */
public class CardRecordAssembler {

	// private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";

	/**
	 * 数据转换
	 */
	public static List<CardRecord> convert(List<Employee> employeeList,
			List<Card> cardList, Schedule schedule, String endDate) {

		List<CardRecord> result = new ArrayList<CardRecord>();

		// 分组
		Map<Long, List<Card>> map = new HashMap<Long, List<Card>>();
		for (Employee employee : employeeList) {
			for (Card card : cardList) {

				if (!employee.id.equals(card.employeeId)) {
					continue;
				}
				if (map.containsKey(employee.id)) {
					map.get(employee.id).add(card);
				} else {
					List<Card> list = new ArrayList<Card>();
					list.add(card);
					map.put(employee.id, list);
				}
			}
		}

		// 设置天数
		for (Entry<Long, List<Card>> entry : map.entrySet()) {
			List<Card> list = entry.getValue();
			if (list.size() == 0) {
				continue;
			}
			setCardRecord(list, result);
		}

		// 排序
		Collections.sort(result, new Comparator<CardRecord>() {
			@Override
			public int compare(CardRecord o1, CardRecord o2) {
				return o1.date.compareTo(o2.date);
			}
		});
		Collections.sort(result, new Comparator<CardRecord>() {
			@Override
			public int compare(CardRecord o1, CardRecord o2) {
				return o1.employeeCode.compareTo(o2.employeeCode);
			}
		});

		// 跳过
		List<Card> skipList = new ArrayList<Card>();
		List<CardRecord> nightList = new ArrayList<CardRecord>();
		List<CardRecord> dayList = new ArrayList<CardRecord>();

		// 设置日期
		CardRecord lastCard = null;
		for (CardRecord cardRecord : result) {
			List<Card> cardsList = map.get(cardRecord.employeeId);
			setDate(cardRecord,
					cardsList,
					schedule,
					skipList,
					nightList,
					dayList,
					lastCard == null
							|| lastCard.employeeId != cardRecord.employeeId ? null
							: lastCard);
			lastCard = cardRecord;
		}

		Collections.sort(result, new Comparator<CardRecord>() {
			@Override
			public int compare(CardRecord o1, CardRecord o2) {
				return o1.date.compareTo(o2.date);
			}
		});

		List<CardRecord> removeList = new ArrayList<CardRecord>();
		String[] parsePatterns = { "yyyy-MM-dd", "yyyy-M-dd", "yyyy-M-d" };
		Date end = null;
		try {

			end = DateUtils.parseDate(endDate, parsePatterns);
		} catch (Exception e) {
		}

		// 移除空数据
		for (CardRecord cardRecord : result) {
			if (cardRecord.morningStart == null
					&& cardRecord.morningEnd == null
					&& cardRecord.afternoonStart == null
					&& cardRecord.afternoonEnd == null
					&& cardRecord.nightStart == null
					&& cardRecord.nightEnd == null && cardRecord.n1 == null
					&& cardRecord.n2 == null && cardRecord.n4 == null
					&& cardRecord.n3 == null) {
				removeList.add(cardRecord);
				continue;
			}

			if (end != null) {
				Date date = null;
				try {

					date = DateUtils.parseDate(cardRecord.date, parsePatterns);
				} catch (Exception e) {
				}
				if (date != null && date.after(end)) {
					removeList.add(cardRecord);
				}
			}
		}

		for (CardRecord cardRecord : removeList) {
			result.remove(cardRecord);
		}
		return result;
	}

	/**
	 * 设置日期
	 */
	private static void setDate(CardRecord cardRecord, List<Card> cardList,
			Schedule schedule, List<Card> skipList, List<CardRecord> nightList,
			List<CardRecord> dayList, CardRecord lastCard) {

		// 白班上午
		if (schedule.morningId != null) {
			setMorning(cardRecord, cardList, schedule, skipList, nightList);
		}
		// 白班下午
		if (schedule.afternoonId != null) {
			setAfternoon(cardRecord, cardList, schedule, skipList, dayList);
		}
		// 夜班
		if (schedule.nightId != null) {
			setNight(cardRecord, cardList, schedule, skipList, nightList,
					dayList);
		}

		// 交换时间
		if (cardRecord.afternoonStart != null && cardRecord.morningEnd != null
				&& cardRecord.morningEnd.after(cardRecord.afternoonStart)) {
			Date morningEnd = cardRecord.morningEnd;
			cardRecord.morningEnd = cardRecord.afternoonStart;
			cardRecord.afternoonStart = morningEnd;
		}
		if (cardRecord.afternoonEnd != null && cardRecord.nightStart != null
				&& cardRecord.afternoonEnd.after(cardRecord.nightStart)) {
			Date afternoonEnd = cardRecord.afternoonEnd;
			cardRecord.afternoonEnd = cardRecord.nightStart;
			cardRecord.nightStart = afternoonEnd;
		}

		// 修正优先上午上班
		if (lastCard != null && lastCard.nightEnd != null
				&& lastCard.nightStart == null
				&& cardRecord.morningStart == null) {

			Date nightEnd = lastCard.nightEnd;
			fixMorningStart(cardRecord, cardList, schedule, skipList,
					nightList, lastCard);

			if (cardRecord.morningStart != null
					&& cardRecord.morningStart == nightEnd) {
				lastCard.nightEnd = null;
			}
		}

		// 修正下午下班多次刷脸
		if (lastCard != null && lastCard.nightStart != null
				&& cardRecord.morningEnd != null
				&& cardRecord.morningStart == null) {
			fixMorningNextStart(cardRecord, cardList, schedule, skipList,
					nightList, lastCard);
			if (cardRecord.morningStart != null) {
				if (cardRecord.morningStart == lastCard.n1) {
					lastCard.n1 = null;
				}
				if (cardRecord.morningStart == lastCard.n2) {
					lastCard.n2 = null;
				}
				if (cardRecord.morningStart == lastCard.n3) {
					lastCard.n3 = null;
				}
				if (cardRecord.morningStart == lastCard.n4) {
					lastCard.n4 = null;
				}
			}
		}
	}

	private static void fixMorningNextStart(CardRecord cardRecord,
			List<Card> cardList, Schedule schedule, List<Card> skipList,
			List<CardRecord> nightList, CardRecord lastCard) {

		Calendar calendarStart = Calendar.getInstance();
		String[] dateStr = cardRecord.date.split("-");
		calendarStart.set(Integer.valueOf(dateStr[0]),
				Integer.valueOf(dateStr[1]) - 1, Integer.valueOf(dateStr[2]),
				Integer.valueOf(schedule.morningStartTime.substring(0, 2)),
				Integer.valueOf(schedule.morningStartTime.substring(2, 4)), 0);

		Calendar calendarEnd = Calendar.getInstance();
		calendarEnd.setTime(calendarStart.getTime());
		calendarEnd.set(Calendar.SECOND, schedule.morningEndTime * 60);

		Calendar calendarStartBefore = Calendar.getInstance();
		calendarStartBefore.setTime(calendarStart.getTime());
		calendarStartBefore.set(Calendar.SECOND,
				-schedule.morningBeforeStart * 60);

		Calendar calendarStartAfter = Calendar.getInstance();
		calendarStartAfter.setTime(calendarStart.getTime());
		calendarStartAfter
				.set(Calendar.SECOND, schedule.morningAfterStart * 60);

		Calendar calendarEndBefore = Calendar.getInstance();
		calendarEndBefore.setTime(calendarEnd.getTime());
		calendarEndBefore.set(Calendar.SECOND, -schedule.morningBeforeEnd * 60);

		Calendar calendarEndAfter = Calendar.getInstance();
		calendarEndAfter.setTime(calendarEnd.getTime());
		calendarEndAfter.set(Calendar.SECOND, schedule.morningAfterEnd * 60);

		// 上班
		if (cardRecord.morningStart == null) {
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {
				if (card.date == null) {
					continue;
				}

				if (card.date.before(calendarStart.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					cardRecord.morningStart = card.date;

					if (!skipList.contains(card)) {
						skipList.add(card);
					}

					for (Card used : usedList) {
						skipList.remove(used);
					}
					break;
				}
				if (card.date.before(calendarStartAfter.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					if (cardRecord.morningStart == null) {
						cardRecord.morningStart = card.date;
						if (!skipList.contains(card)) {
							skipList.add(card);
							usedList.add(card);
						}

						continue;
					} else if (cardRecord.morningStart.before(card.date)) {
						cardRecord.morningStart = card.date;
						if (!skipList.contains(card)) {
							skipList.add(card);
							usedList.add(card);
						}
					}
				}
			}
		}
	}

	/**
	 * 修正优先上午上班
	 */
	private static void fixMorningStart(CardRecord cardRecord,
			List<Card> cardList, Schedule schedule, List<Card> skipList,
			List<CardRecord> nightList, CardRecord lastCard) {

		Calendar calendarStart = Calendar.getInstance();
		String[] dateStr = cardRecord.date.split("-");
		calendarStart.set(Integer.valueOf(dateStr[0]),
				Integer.valueOf(dateStr[1]) - 1, Integer.valueOf(dateStr[2]),
				Integer.valueOf(schedule.morningStartTime.substring(0, 2)),
				Integer.valueOf(schedule.morningStartTime.substring(2, 4)), 0);
		// calendarStart.add(Calendar.DATE, 1);

		Calendar calendarEnd = Calendar.getInstance();
		calendarEnd.setTime(calendarStart.getTime());
		calendarEnd.set(Calendar.SECOND, schedule.morningEndTime * 60);

		Calendar calendarStartBefore = Calendar.getInstance();
		calendarStartBefore.setTime(calendarStart.getTime());
		calendarStartBefore.set(Calendar.SECOND,
				-schedule.morningBeforeStart * 60);

		Calendar calendarStartAfter = Calendar.getInstance();
		calendarStartAfter.setTime(calendarStart.getTime());
		calendarStartAfter
				.set(Calendar.SECOND, schedule.morningAfterStart * 60);

		Calendar calendarEndBefore = Calendar.getInstance();
		calendarEndBefore.setTime(calendarEnd.getTime());
		calendarEndBefore.set(Calendar.SECOND, -schedule.morningBeforeEnd * 60);

		Calendar calendarEndAfter = Calendar.getInstance();
		calendarEndAfter.setTime(calendarEnd.getTime());
		calendarEndAfter.set(Calendar.SECOND, schedule.morningAfterEnd * 60);

		// 上班
		if (cardRecord.morningStart == null) {
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {
				if (skipList.contains(card) && lastCard.nightEnd != card.date) {
					continue;
				}

				if (card.date.before(calendarStart.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					cardRecord.morningStart = card.date;

					skipList.add(card);
					for (Card used : usedList) {
						skipList.remove(used);
					}
					break;
				}
				if (card.date.before(calendarStartAfter.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					if (cardRecord.morningStart == null) {
						cardRecord.morningStart = card.date;
						skipList.add(card);
						usedList.add(card);

						continue;
					} else if (cardRecord.morningStart.before(card.date)) {
						cardRecord.morningStart = card.date;
						skipList.add(card);
						usedList.add(card);
					}
				}
			}
		}
	}

	private static void setMorning(CardRecord cardRecord, List<Card> cardList,
			Schedule schedule, List<Card> skipList, List<CardRecord> nightList) {

		Calendar calendarStart = Calendar.getInstance();
		String[] dateStr = cardRecord.date.split("-");
		calendarStart.set(Integer.valueOf(dateStr[0]),
				Integer.valueOf(dateStr[1]) - 1, Integer.valueOf(dateStr[2]),
				Integer.valueOf(schedule.morningStartTime.substring(0, 2)),
				Integer.valueOf(schedule.morningStartTime.substring(2, 4)), 0);

		Calendar calendarEnd = Calendar.getInstance();
		calendarEnd.setTime(calendarStart.getTime());
		calendarEnd.set(Calendar.SECOND, schedule.morningEndTime * 60);

		Calendar calendarStartBefore = Calendar.getInstance();
		calendarStartBefore.setTime(calendarStart.getTime());
		calendarStartBefore.set(Calendar.SECOND,
				-schedule.morningBeforeStart * 60);

		Calendar calendarStartAfter = Calendar.getInstance();
		calendarStartAfter.setTime(calendarStart.getTime());
		calendarStartAfter
				.set(Calendar.SECOND, schedule.morningAfterStart * 60);

		Calendar calendarEndBefore = Calendar.getInstance();
		calendarEndBefore.setTime(calendarEnd.getTime());
		calendarEndBefore.set(Calendar.SECOND, -schedule.morningBeforeEnd * 60);

		Calendar calendarEndAfter = Calendar.getInstance();
		calendarEndAfter.setTime(calendarEnd.getTime());
		calendarEndAfter.set(Calendar.SECOND, schedule.morningAfterEnd * 60);

		// 上班
		if (cardRecord.morningStart == null) {
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {
				if (skipList.contains(card)) {
					continue;
				}

				if (card.date.before(calendarStart.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					cardRecord.morningStart = card.date;
					skipList.add(card);
					for (Card used : usedList) {
						skipList.remove(used);
					}
					break;
				}
				if (card.date.before(calendarStartAfter.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					if (cardRecord.morningStart == null) {
						cardRecord.morningStart = card.date;
						skipList.add(card);
						usedList.add(card);
						continue;
					} else if (cardRecord.morningStart.before(card.date)) {
						cardRecord.morningStart = card.date;
						skipList.add(card);
						usedList.add(card);
					}
				}
			}
		}
		if (cardRecord.morningStart == null) {
			Date morningStart = null;
			Card skipCard = null;
			for (Card card : cardList) {
				if (card.date.before(calendarStart.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					morningStart = card.date;
					skipCard = card;
					break;
				}
				if (card.date.before(calendarStartAfter.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					if (cardRecord.morningStart == null) {
						morningStart = card.date;
						skipCard = card;
						continue;
					} else if (cardRecord.morningStart.before(card.date)) {
						morningStart = card.date;
						skipCard = card;
					}
				}
			}

			if (morningStart != null) {
				CardRecord record = null;
				for (CardRecord item : nightList) {
					if (item.employeeId == cardRecord.employeeId
							&& item.nightEnd == morningStart) {
						record = item;
						break;
					}
				}
				if (record != null) {
					cardRecord.morningStart = morningStart;
					record.nightEnd = null;
					nightList.remove(record);
					skipList.add(skipCard);
				}
			}
		}

		// 下班
		if (cardRecord.morningEnd == null) {
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {
				if (skipList.contains(card)) {
					continue;
				}

				if (card.date.after(calendarEnd.getTime())
						&& card.date.before(calendarEndAfter.getTime())) {
					cardRecord.morningEnd = card.date;
					skipList.add(card);
					for (Card used : usedList) {
						skipList.remove(used);
					}
					break;
				}
				if (card.date.after(calendarEndBefore.getTime())
						&& card.date.before(calendarEndAfter.getTime())) {
					if (cardRecord.morningEnd == null) {
						cardRecord.morningEnd = card.date;
						skipList.add(card);
						usedList.add(card);
						continue;
					} else if (cardRecord.morningEnd.after(card.date)) {
						cardRecord.morningEnd = card.date;
						skipList.add(card);
						usedList.add(card);
					}
				}
			}
		}

	}

	private static void fixMorningEnd(CardRecord cardRecord, Schedule schedule,
			List<Card> cardList, List<Card> skipList) {
		Calendar calendarStart = Calendar.getInstance();
		String[] dateStr = cardRecord.date.split("-");
		calendarStart.set(Integer.valueOf(dateStr[0]),
				Integer.valueOf(dateStr[1]) - 1, Integer.valueOf(dateStr[2]),
				Integer.valueOf(schedule.morningStartTime.substring(0, 2)),
				Integer.valueOf(schedule.morningStartTime.substring(2, 4)), 0);

		Calendar calendarEnd = Calendar.getInstance();
		calendarEnd.setTime(calendarStart.getTime());
		calendarEnd.set(Calendar.SECOND, schedule.morningEndTime * 60);

		Calendar calendarStartBefore = Calendar.getInstance();
		calendarStartBefore.setTime(calendarStart.getTime());
		calendarStartBefore.set(Calendar.SECOND,
				-schedule.morningBeforeStart * 60);

		Calendar calendarStartAfter = Calendar.getInstance();
		calendarStartAfter.setTime(calendarStart.getTime());
		calendarStartAfter
				.set(Calendar.SECOND, schedule.morningAfterStart * 60);

		Calendar calendarEndBefore = Calendar.getInstance();
		calendarEndBefore.setTime(calendarEnd.getTime());
		calendarEndBefore.set(Calendar.SECOND, -schedule.morningBeforeEnd * 60);

		Calendar calendarEndAfter = Calendar.getInstance();
		calendarEndAfter.setTime(calendarEnd.getTime());
		calendarEndAfter.set(Calendar.SECOND, schedule.morningAfterEnd * 60);

		Date morningEnd = cardRecord.morningEnd;
		for (Card card : cardList) {
			if (skipList.contains(card) && card.date != morningEnd) {
				continue;
			}

			if (card.date.after(calendarEndBefore.getTime())
					&& card.date.before(calendarEndAfter.getTime())) {
				if (cardRecord.morningEnd == null) {
					cardRecord.morningEnd = card.date;
					skipList.add(card);
				} else if (cardRecord.morningEnd.after(card.date)) {
					cardRecord.morningEnd = card.date;
					skipList.add(card);
				}
			}
		}
	}

	private static void fixAfternoonEnd(CardRecord cardRecord,
			Schedule schedule, List<Card> cardList, List<Card> skipList) {
		Calendar calendarStart = Calendar.getInstance();
		String[] dateStr = cardRecord.date.split("-");
		calendarStart
				.set(Integer.valueOf(dateStr[0]),
						Integer.valueOf(dateStr[1]) - 1, Integer
								.valueOf(dateStr[2]), Integer
								.valueOf(schedule.afternoonStartTime.substring(
										0, 2)), Integer
								.valueOf(schedule.afternoonStartTime.substring(
										2, 4)), 0);

		Calendar calendarEnd = Calendar.getInstance();
		calendarEnd.setTime(calendarStart.getTime());
		calendarEnd.set(Calendar.SECOND, schedule.afternoonEndTime * 60);

		Calendar calendarStartBefore = Calendar.getInstance();
		calendarStartBefore.setTime(calendarStart.getTime());
		calendarStartBefore.set(Calendar.SECOND,
				-schedule.afternoonBeforeStart * 60);

		Calendar calendarStartAfter = Calendar.getInstance();
		calendarStartAfter.setTime(calendarStart.getTime());
		calendarStartAfter.set(Calendar.SECOND,
				schedule.afternoonAfterStart * 60);

		Calendar calendarEndBefore = Calendar.getInstance();
		calendarEndBefore.setTime(calendarEnd.getTime());

		calendarEndBefore.set(Calendar.SECOND,
				-schedule.afternoonBeforeEnd * 60);

		Calendar calendarEndAfter = Calendar.getInstance();
		calendarEndAfter.setTime(calendarEnd.getTime());

		calendarEndAfter.set(Calendar.SECOND, schedule.afternoonAfterEnd * 60);

		Date afternoonEnd = cardRecord.afternoonEnd;
		for (Card card : cardList) {
			if (skipList.contains(card) && card.date != afternoonEnd) {
				continue;
			}

			if (card.date.after(calendarEndBefore.getTime())
					&& card.date.before(calendarEndAfter.getTime())) {
				if (cardRecord.afternoonEnd == null) {
					cardRecord.afternoonEnd = card.date;
					skipList.add(card);
				} else if (cardRecord.afternoonEnd.after(card.date)) {
					cardRecord.afternoonEnd = card.date;
					skipList.add(card);
				}
			}
		}
	}

	private static void setAfternoon(CardRecord cardRecord,
			List<Card> cardList, Schedule schedule, List<Card> skipList,
			List<CardRecord> dayList) {
		Calendar calendarStart = Calendar.getInstance();
		String[] dateStr = cardRecord.date.split("-");
		calendarStart
				.set(Integer.valueOf(dateStr[0]),
						Integer.valueOf(dateStr[1]) - 1, Integer
								.valueOf(dateStr[2]), Integer
								.valueOf(schedule.afternoonStartTime.substring(
										0, 2)), Integer
								.valueOf(schedule.afternoonStartTime.substring(
										2, 4)), 0);

		Calendar calendarEnd = Calendar.getInstance();
		calendarEnd.setTime(calendarStart.getTime());
		calendarEnd.set(Calendar.SECOND, schedule.afternoonEndTime * 60);

		Calendar calendarStartBefore = Calendar.getInstance();
		calendarStartBefore.setTime(calendarStart.getTime());
		calendarStartBefore.set(Calendar.SECOND,
				-schedule.afternoonBeforeStart * 60);

		Calendar calendarStartAfter = Calendar.getInstance();
		calendarStartAfter.setTime(calendarStart.getTime());
		calendarStartAfter.set(Calendar.SECOND,
				schedule.afternoonAfterStart * 60);

		Calendar calendarEndBefore = Calendar.getInstance();
		calendarEndBefore.setTime(calendarEnd.getTime());

		calendarEndBefore.set(Calendar.SECOND,
				-schedule.afternoonBeforeEnd * 60);

		Calendar calendarEndAfter = Calendar.getInstance();
		calendarEndAfter.setTime(calendarEnd.getTime());

		calendarEndAfter.set(Calendar.SECOND, schedule.afternoonAfterEnd * 60);

		// 上班
		if (cardRecord.afternoonStart == null) {
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {
				if (skipList.contains(card)) {
					continue;
				}

				if (card.date.before(calendarStart.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					cardRecord.afternoonStart = card.date;
					skipList.add(card);
					for (Card used : usedList) {
						skipList.remove(used);
					}
					break;
				}
				if (card.date.before(calendarStartAfter.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					if (cardRecord.afternoonStart == null) {
						cardRecord.afternoonStart = card.date;
						skipList.add(card);
						usedList.add(card);
						continue;
					} else if (cardRecord.afternoonStart.before(card.date)) {
						cardRecord.afternoonStart = card.date;
						skipList.add(card);
						usedList.add(card);
					}
				}
			}

			// 修正上午下班时间
			if (cardRecord.afternoonStart == null
					&& cardRecord.morningEnd != null) {
				Date morningEnd = cardRecord.morningEnd;
				fixMorningEnd(cardRecord, schedule, cardList, skipList);
				if (cardRecord.morningEnd != null) {
					usedList.clear();
					for (Card card : cardList) {
						if (skipList.contains(card) && morningEnd != card.date) {
							continue;
						}

						if (card.date.before(calendarStart.getTime())
								&& card.date.after(calendarStartBefore
										.getTime())) {
							cardRecord.afternoonStart = card.date;
							skipList.add(card);
							for (Card used : usedList) {
								skipList.remove(used);
							}
							break;
						}
						if (card.date.before(calendarStartAfter.getTime())
								&& card.date.after(calendarStartBefore
										.getTime())) {
							if (cardRecord.afternoonStart == null) {
								cardRecord.afternoonStart = card.date;
								skipList.add(card);
								usedList.add(card);
								continue;
							} else if (cardRecord.afternoonStart
									.before(card.date)) {
								cardRecord.afternoonStart = card.date;
								skipList.add(card);
								usedList.add(card);
							}
						}
					}
				}
			}
		}

		// 下班
		if (cardRecord.afternoonEnd == null) {
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {
				if (skipList.contains(card)) {
					continue;
				}

				if (card.date.after(calendarEnd.getTime())
						&& card.date.before(calendarEndAfter.getTime())) {
					cardRecord.afternoonEnd = card.date;
					skipList.add(card);
					for (Card used : usedList) {
						skipList.remove(used);
					}
					break;
				}
				if (card.date.after(calendarEndBefore.getTime())
						&& card.date.before(calendarEndAfter.getTime())) {
					if (cardRecord.afternoonEnd == null) {
						cardRecord.afternoonEnd = card.date;
						skipList.add(card);
						usedList.add(card);
						continue;
					} else if (cardRecord.afternoonEnd.after(card.date)) {
						cardRecord.afternoonEnd = card.date;
						skipList.add(card);
						usedList.add(card);
					}
				}
			}
		}

		if (cardRecord.afternoonEnd != null
				&& cardRecord.afternoonStart == null) {
			dayList.add(cardRecord);
		}
	}

	/**
	 * 夜班
	 */
	private static void setNight(CardRecord cardRecord, List<Card> cardList,
			Schedule schedule, List<Card> skipList, List<CardRecord> nightList,
			List<CardRecord> dayList) {
		Calendar calendarStart = Calendar.getInstance();
		String[] dateStr = cardRecord.date.split("-");
		calendarStart.set(Integer.valueOf(dateStr[0]),
				Integer.valueOf(dateStr[1]) - 1, Integer.valueOf(dateStr[2]),
				Integer.valueOf(schedule.nightStartTime.substring(0, 2)),
				Integer.valueOf(schedule.nightStartTime.substring(2, 4)), 0);

		Calendar calendarEnd = Calendar.getInstance();
		calendarEnd.setTime(calendarStart.getTime());
		calendarEnd.set(Calendar.SECOND, schedule.nightEndTime * 60);

		Calendar calendarStartBefore = Calendar.getInstance();
		calendarStartBefore.setTime(calendarStart.getTime());
		calendarStartBefore.set(Calendar.SECOND,
				-schedule.nightBeforeStart * 60);

		Calendar calendarStartAfter = Calendar.getInstance();
		calendarStartAfter.setTime(calendarStart.getTime());
		calendarStartAfter.set(Calendar.SECOND, schedule.nightAfterStart * 60);

		Calendar calendarEndBefore = Calendar.getInstance();
		calendarEndBefore.setTime(calendarEnd.getTime());
		calendarEndBefore.set(Calendar.SECOND, -schedule.nightBeforeEnd * 60);

		Calendar calendarEndAfter = Calendar.getInstance();
		calendarEndAfter.setTime(calendarEnd.getTime());
		calendarEndAfter.set(Calendar.SECOND, schedule.nightAfterEnd * 60);

		// 上班
		if (cardRecord.nightStart == null) {
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {
				if (skipList.contains(card)) {
					continue;
				}

				if (card.date.before(calendarStart.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					cardRecord.nightStart = card.date;

					skipList.add(card);
					for (Card used : usedList) {
						skipList.remove(used);
					}
					break;
				}
				if (card.date.before(calendarStartAfter.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					if (cardRecord.nightStart == null) {
						cardRecord.nightStart = card.date;
						skipList.add(card);
						usedList.add(card);
						continue;
					} else if (cardRecord.nightStart.before(card.date)) {
						cardRecord.nightStart = card.date;
						skipList.add(card);
						usedList.add(card);
					}
				}
			}
		}

		// 下班
		if (cardRecord.nightEnd == null) {
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {

				if (skipList.contains(card)) {
					continue;
				}

				if (card.date.after(calendarEnd.getTime())
						&& card.date.before(calendarEndAfter.getTime())) {
					cardRecord.nightEnd = card.date;
					skipList.add(card);
					for (Card used : usedList) {
						skipList.remove(used);
					}

					break;
				}
				if (card.date.after(calendarEndBefore.getTime())
						&& card.date.before(calendarEndAfter.getTime())) {
					if (cardRecord.nightEnd == null) {
						cardRecord.nightEnd = card.date;
						skipList.add(card);
						usedList.add(card);
						continue;
					} else if (cardRecord.nightEnd.after(card.date)) {
						cardRecord.nightEnd = card.date;
						skipList.add(card);
						usedList.add(card);
					}
				}
			}
		}

		if (cardRecord.nightStart == null && cardRecord.afternoonStart == null
				&& cardRecord.afternoonEnd != null
				&& cardRecord.nightEnd != null) {
			List<Card> usedList = new ArrayList<Card>();
			Date afternoonEnd = cardRecord.afternoonEnd;
			fixAfternoonEnd(cardRecord, schedule, cardList, skipList);

			if (cardRecord.afternoonEnd != null) {
				usedList.clear();
				for (Card card : cardList) {
					if (skipList.contains(card) && afternoonEnd != card.date) {
						continue;
					}

					if (card.date.before(calendarStart.getTime())
							&& card.date.after(calendarStartBefore.getTime())) {
						cardRecord.nightStart = card.date;

						skipList.add(card);
						for (Card used : usedList) {
							skipList.remove(used);
						}
						break;
					}
					if (card.date.before(calendarStartAfter.getTime())
							&& card.date.after(calendarStartBefore.getTime())) {
						if (cardRecord.nightStart == null) {
							cardRecord.nightStart = card.date;
							skipList.add(card);
							usedList.add(card);
							continue;
						} else if (cardRecord.nightStart.before(card.date)) {
							cardRecord.nightStart = card.date;
							skipList.add(card);
							usedList.add(card);
						}
					}
				}

				if (afternoonEnd == cardRecord.nightStart) {
					cardRecord.afternoonEnd = null;
				}
			}
		}

		// 巡检
		setCheck(schedule, cardRecord, cardList, calendarStart, calendarEnd,
				calendarEndBefore, calendarStartAfter, skipList,
				new ArrayList<Date>());

		// 修正移位
		fixMoveNight(schedule, cardRecord, cardList, calendarStart,
				calendarEnd, calendarStartBefore, calendarEndBefore,
				calendarStartAfter, skipList);
	}

	/**
	 * 修正位移
	 */
	private static void fixMoveNight(Schedule schedule, CardRecord cardRecord,
			List<Card> cardList, Calendar calendarStart, Calendar calendarEnd,
			Calendar calendarStartBefore, Calendar calendarEndBefore,
			Calendar calendarStartAfter, List<Card> skipList) {
		if (cardRecord.afternoonStart == null
				&& cardRecord.afternoonEnd != null
				&& cardRecord.nightStart != null && cardRecord.nightEnd != null) {
			Date nightStart = null;
			List<Card> usedList = new ArrayList<Card>();
			for (Card card : cardList) {
				if (skipList.contains(card)
						&& cardRecord.afternoonEnd == card.date) {
					continue;
				}

				if (card.date.before(calendarStart.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					nightStart = card.date;
					if (!skipList.contains(card)) {
						skipList.add(card);
					}
					for (Card used : usedList) {
						skipList.remove(used);
					}
					break;
				}
				if (card.date.before(calendarStartAfter.getTime())
						&& card.date.after(calendarStartBefore.getTime())) {
					if (nightStart == null) {
						nightStart = card.date;
						for (Card used : usedList) {
							skipList.remove(used);
							usedList.add(card);
						}
						continue;
					} else if (nightStart.before(card.date)) {
						nightStart = card.date;
						for (Card used : usedList) {
							skipList.remove(used);
							usedList.add(card);
						}
					}
				}
			}
			if (nightStart != null && cardRecord.afternoonEnd == nightStart) {
				cardRecord.nightStart = nightStart;
				cardRecord.afternoonEnd = null;

				List<Date> dateSkipList = new ArrayList<Date>();
				if (cardRecord.n1 != null) {
					dateSkipList.add(cardRecord.n1);
					if (cardRecord.n2 != null) {
						dateSkipList.add(cardRecord.n2);
						if (cardRecord.n3 != null) {
							dateSkipList.add(cardRecord.n3);
							if (cardRecord.n4 != null) {
								dateSkipList.add(cardRecord.n4);
							}
						}
					}
				}
				setCheck(schedule, cardRecord, cardList, calendarStart,
						calendarEnd, calendarEndBefore, calendarStartAfter,
						skipList, dateSkipList);
			}
		}
	}

	/**
	 * 巡检
	 */
	private static void setCheck(Schedule schedule, CardRecord cardRecord,
			List<Card> cardList, Calendar calendarStart, Calendar calendarEnd,
			Calendar calendarEndBefore, Calendar calendarStartAfter,
			List<Card> skipList, List<Date> dateSkipList) {
		if (ArrayUtils.isNotEmpty(schedule.nightCheckList)) {

			Arrays.sort(schedule.nightCheckList, new Comparator<NightCheck>() {
				@Override
				public int compare(NightCheck o1, NightCheck o2) {
					return Integer.valueOf(o1.orderBy).compareTo(
							Integer.valueOf(o2.orderBy));
				}
			});

			List<Card> nightCardList = new ArrayList<Card>();
			if (cardRecord.nightStart != null) {
				for (Card card : cardList) {
					if (card.date.before(calendarEnd.getTime())
							&& card.date.after(cardRecord.nightStart)) {
						nightCardList.add(card);
					}
				}

				Collections.sort(nightCardList, new Comparator<Card>() {

					@Override
					public int compare(Card o1, Card o2) {
						return o1.date.compareTo(o2.date);
					}
				});
			}

			if (cardRecord.n1 == null) {
				NightCheck n1 = schedule.nightCheckList[0];
				for (Card card : nightCardList) {
					if (skipList.contains(card)
							&& (CollectionUtils.isEmpty(dateSkipList) || !dateSkipList
									.contains(card.date))) {
						continue;
					}
					if (n1.startTime == null || n1.endTime == null) {
						if (card.date.before(calendarEndBefore.getTime())
								&& card.date
										.after(calendarStartAfter.getTime())) {
							cardRecord.n1 = card.date;
							if (!skipList.contains(card)) {
								skipList.add(card);
							}

							break;
						}
					} else {
						Calendar start = getCalendar(calendarStart,
								n1.startTime);
						Calendar end = getCalendar(calendarStart, n1.endTime);
						if (card.date.after(start.getTime())
								&& card.date.before(end.getTime())) {
							cardRecord.n1 = card.date;
							if (!skipList.contains(card)) {
								skipList.add(card);
							}
							break;
						}
					}
				}
			}

			if (schedule.nightCheckList.length > 1 && cardRecord.n2 == null) {
				NightCheck n2 = schedule.nightCheckList[1];
				for (Card card : nightCardList) {
					if (skipList.contains(card)
							&& (CollectionUtils.isEmpty(dateSkipList) || !dateSkipList
									.contains(card.date))) {
						continue;
					}
					if (n2.startTime == null || n2.endTime == null) {
						if (card.date.before(calendarEndBefore.getTime())
								&& ((cardRecord.n1 != null && card.date
										.after(cardRecord.n1)) || (card.date
										.after(calendarStartAfter.getTime())))) {
							cardRecord.n2 = card.date;
							if (!skipList.contains(card)) {
								skipList.add(card);
							}
							break;
						}
					} else {
						Calendar start = getCalendar(calendarStart,
								n2.startTime);
						Calendar end = getCalendar(calendarStart, n2.endTime);
						if (card.date.after(start.getTime())
								&& card.date.before(end.getTime())) {
							cardRecord.n2 = card.date;
							if (!skipList.contains(card)) {
								skipList.add(card);
							}
							break;
						}
					}
				}
			}

			if (schedule.nightCheckList.length > 2 && cardRecord.n3 == null) {
				NightCheck n3 = schedule.nightCheckList[2];
				for (Card card : nightCardList) {
					if (skipList.contains(card)
							&& (CollectionUtils.isEmpty(dateSkipList) || !dateSkipList
									.contains(card.date))) {
						continue;
					}

					if (n3.startTime == null || n3.endTime == null) {
						if (card.date.before(calendarEndBefore.getTime())
								&& ((cardRecord.n2 != null && card.date
										.after(cardRecord.n2)) || (card.date
										.after(calendarStartAfter.getTime())))) {
							cardRecord.n3 = card.date;
							if (!skipList.contains(card)) {
								skipList.add(card);
							}
							break;
						}
					} else {
						Calendar start = getCalendar(calendarStart,
								n3.startTime);
						Calendar end = getCalendar(calendarStart, n3.endTime);
						if (card.date.after(start.getTime())
								&& card.date.before(end.getTime())) {
							cardRecord.n3 = card.date;
							if (!skipList.contains(card)) {
								skipList.add(card);
							}
							break;
						}
					}
				}
			}

			if (schedule.nightCheckList.length > 3 && cardRecord.n4 == null) {
				NightCheck n4 = schedule.nightCheckList[3];
				for (Card card : nightCardList) {
					if (skipList.contains(card)
							&& (CollectionUtils.isEmpty(dateSkipList) || !dateSkipList
									.contains(card.date))) {
						continue;
					}

					if (n4.startTime == null || n4.endTime == null) {
						if (card.date.before(calendarEnd.getTime())
								&& ((cardRecord.n3 != null && card.date
										.after(cardRecord.n3)) || (card.date
										.after(calendarStartAfter.getTime())))) {
							cardRecord.n4 = card.date;
							if (!skipList.contains(card)) {
								skipList.add(card);
							}
							break;
						}
					} else {
						Calendar start = getCalendar(calendarStart,
								n4.startTime);
						Calendar end = getCalendar(calendarStart, n4.endTime);
						if (card.date.after(start.getTime())
								&& card.date.before(end.getTime())) {
							cardRecord.n4 = card.date;
							if (!skipList.contains(card)) {
								skipList.add(card);
							}
							break;
						}
					}
				}
			}
		}
	}

	private static Calendar getCalendar(Calendar start, String time) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(start.get(Calendar.YEAR), start.get(Calendar.MONTH),
				start.get(Calendar.DATE), Integer.valueOf(time.split(":")[0]),
				Integer.valueOf(time.split(":")[1]), 0);
		if (calendar.before(start)) {
			calendar.add(Calendar.DATE, 1);
		}

		return calendar;
	}

	/**
	 * 设置天数
	 */
	private static void setCardRecord(List<Card> list,
			List<CardRecord> recordList) {
		String pattern = "yyyy-MM-dd";
		Card card = list.get(0);

		List<String> dateList = new ArrayList<String>();
		for (Card c : list) {
			String d = DateFormatUtils.format(c.date, pattern);
			if (dateList.contains(d)) {
				continue;
			}

			dateList.add(d);

			CardRecord result = new CardRecord();
			recordList.add(result);

			result.employeeId = card.employeeId;
			result.date = d;
			result.employeeCode = card.employeeCode;
			result.employeeName = card.employeeName;
			result.departmentId = card.departmentId;
			result.departmentName = card.departmentName;
		}
	}
}
